/*
*Copyright 2021-2023 NERCIS
*
*Licensed under the Apache License, Version 2.0 (the "License");
*you may not use this file except in compliance with the License.
*You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing, software
*distributed under the License is distributed on an "AS IS" BASIS,
*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*See the License for the specific language governing permissions and
*limitations under the License.
*/

package cn.ac.nercis.pes.community.controller.login;

import cn.ac.nercis.pes.community.component.dialog.MessageDialog;
import cn.ac.nercis.pes.community.component.dialog.MessageType;
import cn.ac.nercis.pes.community.config.AppConfig;
import cn.ac.nercis.pes.community.controller.MainController;
import cn.ac.nercis.pes.community.controller.base.BaseWindow;
import cn.ac.nercis.pes.community.mapper.manage.UserViewMapper;
import cn.ac.nercis.pes.community.support.FXMLController;
import cn.ac.nercis.pes.community.support.theme.ThemeManager;
import cn.ac.nercis.pes.community.utils.*;
import cn.ac.nercis.pes.community.views.MainView;
import cn.ac.nercis.pes.model.dto.common.ResultCode;
import cn.ac.nercis.pes.service.manage.AuthService;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.net.URL;
import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

/**
 * 登录控制器
 * @author zpy
 * @version 1.0.0
 */
@Slf4j
@FXMLController
public class LoginController extends BaseWindow implements Initializable {

    @FXML
    private StackPane page;
    @FXML
    private BorderPane bodyPane;
    @FXML
    private HBox titleBar;
    @FXML
    private Label titleLabel;
    @FXML
    private ImageView loginImg;
    @FXML
    private Label userIcon;
    @FXML
    private Label pwdIcon;
    @FXML
    private TextField userNameTxt;
    @FXML
    private PasswordField pwdTxt;
    @FXML
    private Label userErrorLbl;
    @FXML
    private Label pwdErrorLbl;
    @FXML
    private Button loginBtn;
    @FXML
    private Button btnMin;
    @FXML
    private Button btnClose;


    private final AuthService authService;
    private final AppConfig appConfig;

    @Autowired
    public LoginController(AuthService authService,
                           AppConfig appConfig) {
        this.authService = authService;
        this.appConfig = appConfig;
    }

    /**
     * 初始化
     */
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        ResizeWindowUtils.appendResizeFunc(GuiStore.getStage(),this.bodyPane);
        this.btnClose.setGraphic(IconUtils.getGlyph("win-close","win-close-icon"));
        this.btnMin.setGraphic(IconUtils.getGlyph("win-min","win-min-icon"));
        this.userIcon.setGraphic(IconUtils.getIcoMoonGlyph("userName"));
        this.pwdIcon.setGraphic(IconUtils.getIcoMoonGlyph("password"));
        this.titleBar.setOnMouseDragged((event)->this.onMouseDragged(event,GuiStore.getStage()));
        this.titleBar.setOnMousePressed(this::onMousePressed);
        this.initControl();
        this.initData();
        this.titleLabel.setText(appConfig.getAppTitle());
        this.userNameTxt.setText("admin");
        this.pwdTxt.setText("123456");
    }

    @FXML
    public void onMinWindow(){
        GuiStore.getStage().setIconified(true);
    }

    @FXML
    public void onClose(){
        AppUtils.exitApp();
    }

    @FXML
    public void login(){
        if(loginValid()){
            doLogin(userNameTxt.getText(),pwdTxt.getText());
        }
    }

    public void initData(){
        this.userErrorLbl.setText("");
        this.pwdErrorLbl.setText("");
    }

    private void initControl(){
        this.loginImg.setImage(ThemeManager.config().getLoginImg());
        userNameTxt.textProperty().addListener((o,oldVal,newVal) -> {
            if (StringUtils.isBlank(newVal)){
                userErrorLbl.setText("用户名不能为空");
                this.loginBtn.setDisable(true);
            }else{
                userErrorLbl.setText("");
                this.loginBtn.setDisable(false);
            }
        });
        pwdTxt.textProperty().addListener((o,oldVal,newVal) -> {
            if (StringUtils.isBlank(newVal)){
                pwdErrorLbl.setText("密码不能为空");
                this.loginBtn.setDisable(true);
            }else{
                pwdErrorLbl.setText("");
                this.loginBtn.setDisable(false);
            }
        });
        bodyPane.setOnKeyPressed(event -> {
            if (event.getCode() == KeyCode.ENTER) {
                if (!loginBtn.isDisable()) {
                    login();
                }
            }
        });
    }

    private boolean loginValid(){
        if (StringUtils.isBlank(userNameTxt.getText())){
            userErrorLbl.setText("用户名不能为空");
            this.loginBtn.setDisable(true);
            return false;
        }
        if (StringUtils.isBlank(pwdTxt.getText())){
            pwdErrorLbl.setText("密码不能为空");
            this.loginBtn.setDisable(true);
            return false;
        }
        return true;
    }

    private void doLogin(String userName,String pwd){
        var loginText = this.loginBtn.getText();
        setLoginState(true,loginText);
        CompletableFuture.supplyAsync(()->this.authService.login(userName,pwd))
                .thenAccept(res-> Platform.runLater(()->{
                    if (StringUtils.equals(res.getCode(), ResultCode.SUCCESS.getCode())) {
                        AppStore.setCurrentUser(UserViewMapper.INSTANCE.toVO(res.getData()));
                        var mainPage = SpringUtils.getBean(MainView.class).getView();
                        setLoginState(false,loginText);
                        GuiStore.getScene().setRoot(mainPage);
                        SpringUtils.getBean(MainController.class).initData();
                    } else {
                        setLoginState(false,loginText);
                        MessageDialog.builder()
                                .withContainer(page)
                                .withType(MessageType.FAIL)
                                .withMessage(res.getMsg())
                                .build().show();
                    }
                }))
                .exceptionally((ex) -> {
                    setLoginState(false,loginText);
                    log.error("登录出错!", ex);
                    return null;
                });
    }

    private void setLoginState(boolean isLogin,String loginText){
        if(isLogin){
            this.loginBtn.setText("登录中...");
            this.loginBtn.setDisable(true);
        }else{
            this.loginBtn.setText(loginText);
            this.loginBtn.setDisable(false);
        }

    }

}